package at.fhj.pse.presentation;

import java.io.IOException;
import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;

import at.fhj.pse.datasource.exception.DatasourceLayerException;
import at.fhj.pse.datasource.model.Employee;
import at.fhj.pse.domain.EmployeeBean;
import at.fhj.pse.domain.exception.DomainLayerException;
import at.fhj.pse.domain.exception.WrongCredentialsException;
import at.fhj.pse.domain.service.SecurePassword;
import at.fhj.pse.presentation.exception.PresentationLayerException;

@ManagedBean(name = "employeeView")
@ViewScoped
public class EmployeeView implements Serializable {

	private static final long serialVersionUID = -7841325500457382028L;

	private String username, password;

	private Long id;

	@EJB(beanName = "EmployeeBeanImpl")
	@ManagedProperty("#{employeeBean}")
	private EmployeeBean employeeBean;

	public EmployeeView() {
		FacesContext context = FacesContext.getCurrentInstance();
		try {
			this.id = (long) context.getExternalContext().getSessionMap()
					.get("currentUserId");
		} catch (NullPointerException ex) {
			this.id = null;
		}
	}

	private Employee employee;

	@PostConstruct
	public void init() {
		retrieve();
	}

	public void retrieve() {
		if (id != null) {
			this.employee = employeeBean.getEmployeeById(id);
		}
	}

	public EmployeeBean getEmployeeBean() {
		return employeeBean;
	}

	// employeeBean is null, therefore @EJB(beanName="EmployeeBeanImpl") added
	// to private EmployeeBean employeeBean;
	public void setEmployeeBean(EmployeeBean employeeBean) {
		this.employeeBean = employeeBean;
	}

	public Employee getEmployee() {
		return this.employee;
	}

	public void forwardToLoginIfNotLoggedIn(ComponentSystemEvent cse) {
		String viewId = FacesContext.getCurrentInstance().getViewRoot()
				.getViewId();
		if (!FacesContext.getCurrentInstance().getExternalContext()
				.getSessionMap().containsKey("currentUserId")
				&& !viewId.startsWith("/login")) {
			FacesContext
					.getCurrentInstance()
					.getApplication()
					.getNavigationHandler()
					.handleNavigation(FacesContext.getCurrentInstance(), null,
							"/login?faces-redirect=true");
		}
	}

	public void login() throws IOException, WrongCredentialsException {
		try {
			Employee emp = employeeBean.login(getUsername(), getPassword());
			FacesContext.getCurrentInstance().addMessage(
					null,
					new FacesMessage(FacesMessage.SEVERITY_INFO, "Success!",
							"Welcome " + emp.getFirstName() + "."));
			FacesContext context = FacesContext.getCurrentInstance();
			context.getExternalContext().getSessionMap()
					.put("currentUserId", emp.getId());
			context.getExternalContext().redirect("index.xhtml");
		} catch (WrongCredentialsException ex) {
			displayErrMsgCheckedException(ex.getMessage());
		} catch (DatasourceLayerException | DomainLayerException ex) {
			displayErrMsgUncheckedException();
		}
	}

	public String logout() {
		employee = null;
		FacesContext.getCurrentInstance().getExternalContext()
				.invalidateSession();
		return "login.xhtml";
	}

	public boolean isLoggedIn() {
		return (employee != null);
	}

	public void displayErrMsgCheckedException(String msg) {
		FacesContext.getCurrentInstance().addMessage(
				null,
				new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error!",
						msg));
	}
	
	public void displayErrMsgUncheckedException() {
		FacesContext.getCurrentInstance().addMessage(
				null,
				new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error!",
						"Unbekannter Fehler ist aufgetreten!"));
	}

	public String getUsername() {
		return this.username;
	}

	public void setUsername(String username) {
		if (username == null) {
			throw new PresentationLayerException("username is null", new IllegalArgumentException());
		}
		this.username = username;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		if (password == null) {
			throw new PresentationLayerException("password is null", new IllegalArgumentException());
		}
		SecurePassword secP = new SecurePassword(password);
		if (secP.getSecPassword() == null) {
			throw new PresentationLayerException("NoSuchAlgorithm", new IllegalStateException());
		} else {
			this.password = secP.getSecPassword();
		}
	}

}